﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using System.Data;
using System.Windows.Forms;
using System.Security.Cryptography;

namespace Common
{
    public static class Util
    {
        public static SqlConnection Conn { get; set; }
        public static Hashtable ConfigData { get; set; }
        public static dsBoleto DSBoleto { get; set; }
        //public static 
        public enum Funcionalidad
        {
            Login,
            UsuarioAlta,
            UsuarioBaja,
            UsuarioModificacion,
            UsuarioConsulta,
            BeneficiarioAlta,
            BeneficiarioBaja,
            BeneficiarioModificacion,
            BeneficiarioConsulta,
            ClienteAlta,
            ClienteBaja,
            ClienteModificacion,
            ClienteConsulta,
            EmpleadoAlta,
            EmpleadoBaja,
            EmpleadoModificacion,
            EmpleadoConsulta,
            RolAlta,
            RolBaja,
            RolModificacion,
            RolConsulta,
            RubroAlta,
            RubroBaja,
            RubroModificacion,
            RubroConsulta,
            CargaAlta,
            CargaBaja,
            CargaModificacion,
            CargaConsulta,
            CompraAlta,
            CompraBaja,
            CompraModificacion,
            CompraConsulta,
            PagoAlta,
            PagoBaja,
            PagoModificacion,
            PagoConsulta,
            MejoresRubrosConsulta,
            TarjetaAlta,
            TarjetaBaja,
            TarjetaModificacion,
            TarjetaConsulta,
            TarjetasPermiumConsulta,
            TopEmpresasConsulta,
            PostNetAlta,
            PostNetBaja,
            PostNetModificacion,
            PostNetConsulta,
            PostNetSelectOne,
            PostNetSelectMany
        }

        public static void SqlConnect()
        {
            Conn = new SqlConnection();
        }

        public static string HashPassword(string p)
        {

            SHA256 hash = SHA256.Create();

            // Convertir la cadena en un array de bytes y calcular hash
            byte[] data = hash.ComputeHash(Encoding.UTF8.GetBytes(p));

            // Copiar cada elemento del array a un
            // StringBuilder en formato hexadecimal
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            return sBuilder.ToString();
        }

        public static T StringToEnum<T>(string name)
        {
            return (T)Enum.Parse(typeof(T), name);
        }
        public static string ExceptionRecursive(Exception ex)
        {
            StringBuilder sbException = new StringBuilder();
            sbException.AppendLine(ex.ToString());
            sbException.AppendLine();

            sbException.AppendLine("\tMensaje: " + ex.Message);
            sbException.AppendLine("\tEn " + ex.Source);
            sbException.AppendLine();
            sbException.AppendLine("\tStackTrace: " + ex.StackTrace);
            if (ex.InnerException != null)
            {
                sbException.AppendLine();
                sbException.AppendLine("\tInnerException!");

                sbException.AppendLine(ExceptionRecursive(ex.InnerException).Replace("\n", "\n\t"));
            }

            return sbException.ToString();
        }

        /// <summary>
        /// Los parametros para la base. El nombre del parametro, el value y su tipo para SQL.
        /// </summary>
        public struct DBParameter
        {
            public string parameterName;
            public object value;
            public DbType dbType;

            public DBParameter(string paramName, object val, DbType type)
            {
                parameterName = paramName;
                value = val;
                dbType = type;
            }

            public override string ToString()
            {
                return parameterName;
            }

            public SqlParameter ToSqlParameter()
            {
                if (parameterName == string.Empty || parameterName == null)
                    throw new ArgumentException("No hay parámetro escrito, el nombre del campo es obligatorio", "parameterName");

                SqlParameter me = new SqlParameter(parameterName, value);
                me.DbType = dbType;

                return me;
            }
        }

        /// <summary>
        /// Genera un SqlCommand que solo requiere
        /// ser ejecutado en la forma que el desarrollador necesite.
        /// </summary>
        /// <param name="StoredProcedure">Nombre del Stored Procedure</param>
        /// <param name="DBParameters">Listado de parametros</param>
        /// <example>SQLCommandBuild("UsuariosRolesFuncionalidadesGet", new List Util.DBParameter())</example>
        /// <returns>El SqlCommand listo para su ejecución.-</returns>
        public static SqlCommand SQLCommandBuild(string StoredProcedure, List<DBParameter> DBParameters)
        {
            string SchemeSP = ConfigData["Scheme"].ToString() + ".";
            if (StoredProcedure.Contains(SchemeSP))
            {
                SchemeSP = string.Empty;
            }
            SqlCommand cmd = new SqlCommand(SchemeSP + StoredProcedure, Conn);
            DBParameters.ForEach(p => cmd.Parameters.Add(p.ToSqlParameter()));
            cmd.CommandType = CommandType.StoredProcedure;

            return cmd;
        }
        /// <summary>
        /// Genera un SqlCommand que solo requiere
        /// ser ejecutado en la forma que el desarrollador necesite.
        /// </summary>
        /// <param name="StoredProcedure">Nombre del Stored Procedure</param>
        /// <example>SQLCommandBuild("UsuariosRolesFuncionalidadesGet")</example>
        /// <returns></returns>
        public static SqlCommand SQLCommandBuild(string StoredProcedure)
        {
            return SQLCommandBuild(StoredProcedure, new List<DBParameter>());
        }

        public static SqlCommand SQLCommandBuild(string StoredProcedure, DBParameter miParam)
        {
            List<DBParameter> ListaDeUnSoloParam = new List<DBParameter>();
            ListaDeUnSoloParam.Add(miParam);
            return SQLCommandBuild(StoredProcedure, ListaDeUnSoloParam);
        }


        /// <summary>
        /// Ejecuta el Select pedido y te lo mapea a las tablas del dataset indicadas
        /// </summary>
        /// <param name="cmd">El SQL Command a ejecutar</param>
        /// <param name="sourceTables">Los sources (los nombres que se les estipula a las consultas)</param>
        /// <param name="datasetTables">Las tablas (en el mismo indice de los sources)</param>
        /// <returns>El dsBoleto con los datos mapeados</returns>
        public static dsBoleto SelectSPtoDatasetSolve(SqlCommand cmd, string[] sourceTables, string[] datasetTables)
        {
            SqlDataAdapter da = new SqlDataAdapter();

            da.SelectCommand = cmd;

            for (int i = 0; i < datasetTables.Length; i++)
            {
                da.TableMappings.Add(sourceTables[i], datasetTables[i]);
            }
            DSBoleto = new dsBoleto();
            DSBoleto.EnforceConstraints = true;
            try
            {
                da.Fill(DSBoleto);

            }
            catch (ConstraintException)
            {
                DSBoleto.EnforceConstraints = false;
                da.Fill(DSBoleto);
              
            }

            return DSBoleto;

            /* Despues en el Datagrid te queda:
             * 
             * DataGrid1.DataSource = miDsBoleto; //una instancia del Dataset
             * DataGrid1.DataMember = "Usuarios"; //Ponele.
             * 
             * Se pueden tener Campos no tipados por el Dataset.
             */
        }

        /// <summary>
        /// Ejecuta el Select pedido y te lo mapea a las tablas del dataset indicadas
        /// </summary>
        /// <param name="cmd">El SQL Command a ejecutar</param>
        /// <param name="datasetTables">Las tablas (en el orden en que se devuelven en el Query)</param>
        /// <returns>El dsBoleto con los datos mapeados</returns>
        public static dsBoleto SelectSPtoDatasetSolve(SqlCommand cmd, string[] datasetTables)
        {
            string[] sourceTables = new string[datasetTables.Length];
            sourceTables[0] = "Table";
            for (int i = 1; i < datasetTables.Length; i++)
            {
                sourceTables[i] = sourceTables[0] + i.ToString();
            }
            #region Ejemplo de Tablas genericas

            /*
           CREATE PROCEDURE dbo.sp_GetCustOrd
           AS
               SELECT * FROM Customers;
               SELECT * FROM Orders;
            
            * Genera Table y Table1 de sources
            */

            #endregion
            return SelectSPtoDatasetSolve(cmd, sourceTables, datasetTables);
        }

        public static List<int> CheckedListBoxToListInt(System.Windows.Forms.CheckedListBox chkList, string DataRowIdName)
        {
            List<int> Ides = new List<int>();
            foreach (DataRowView item in chkList.CheckedItems)
            {
                Ides.Add(int.Parse(item.Row[DataRowIdName].ToString()));
            }
            return Ides;
        }

        public static List<int> ListBoxToListInt(System.Windows.Forms.ListBox myList, string DataRowIdName)
        {
            List<int> Ides = new List<int>();
            foreach (DataRowView item in myList.Items)
            {
                Ides.Add(int.Parse(item.Row[DataRowIdName].ToString()));
            }
            return Ides;
        }

        public static DBParameter BuildSelectQueryUnions(List<int> Ids)
        {
            StringBuilder sbSelect = new StringBuilder();
            if (Ids.Count != 0)
            {
                sbSelect.Append("(");
                for (int i = 0; i < Ids.Count; i++)
                {
                    sbSelect.Append("SELECT ");
                    sbSelect.Append(Ids[i]);
                    sbSelect.Append(" Id ");
                    if (i != Ids.Count - 1)
                    {
                        sbSelect.Append("UNION ");
                    }
                }
                sbSelect.Append(")");
            }
            return new DBParameter("@QueryUnions", sbSelect.ToString(), DbType.String);
        }

        public static void limitarCampoNumericoEntero(KeyPressEventArgs e)
        {
            if (Char.IsDigit(e.KeyChar) || Char.IsControl(e.KeyChar))
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        public static void limitarCampoTexto(KeyPressEventArgs e)
        {
            if (Char.IsLetter(e.KeyChar))
            {
                e.Handled = false;
            }
            else if (Char.IsControl(e.KeyChar))
            {
                e.Handled = false;
            }
            else if (Char.IsSeparator(e.KeyChar))
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }
    }
}
